from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import APIException
import jwt
import re
from rest_framework_jwt.serializers import jwt_decode_handler
from django.conf import settings
from django.utils import timezone
from django.core.cache import cache
from admins.models import Admins
from menu.models import Menu
from menu.serializer import MenuSerializer


# 验证token
class AdminJwtAuth(BaseAuthentication):
    def authenticate(self, request):
        # 接收token
        token = request.META.get('HTTP_TOKEN')
        if token:
            try:
                payload = jwt_decode_handler(token)
            except jwt.ExpiredSignature:
                raise APIException('签名过期!', code=1202)
            except jwt.DecodeError:
                raise APIException('签名验证失败!', code=1203)
            except jwt.InvalidTokenError:
                raise APIException('未知错误!', code=1204)
            # 查询缓存信息
            user = cache.get('admin_{}'.format(payload.get('id')))
            if not user:
                # 缓存里没获取到，走数据库
                try:
                    user_obj = Admins.objects.get(username=payload.get('username'))
                except:
                    raise APIException('账号异常!', code=1103)
                if not user_obj.is_active or timezone.now() < user_obj.date_lock:
                    raise APIException('账号异常!', code=1104)
                user = set_admin_user_cache(user_obj)
            return user, token
        else:
            raise APIException('请先登录!', code=1201)


# 设置用户缓存
def set_admin_user_cache(user_obj):
    if user_obj.role_id:
        if user_obj.role.auth:
            role = user_obj.role.auth.split(',')
        else:
            role = []
    else:
        role = []
    user = {
        'id': user_obj.id,
        'username': user_obj.username,
        'is_superuser': user_obj.is_superuser,
        'role': role
    }
    # 存进缓存
    cache.set('admin_{}'.format(user_obj.id), user, settings.ZEUS_CACHES_TIME)
    return user


# 验证权限
class AdminPermission(BasePermission):
    message = '您无权限访问'

    def has_permission(self, request, view):
        if request.user['is_superuser']:
            return True
        admin_menu_all = self._get_admin_menu_all()
        for admin_menu in admin_menu_all:
            if admin_menu['urls'] and re.match(admin_menu['urls'],
                                               request.path) and request.method == admin_menu['method']:
                if str(admin_menu['id']) in request.user['role']:
                    return True
        raise APIException('您无权限访问!', code=1401)

    # 获取所有菜单
    def _get_admin_menu_all(self):
        menu_all = cache.get('admin_menu_all')
        if not menu_all:
            queryset = Menu.objects.filter(is_delete=False).all()
            ser = MenuSerializer(instance=queryset, many=True)
            menu_all = ser.data
            cache.set('admin_menu_all', menu_all, settings.ZEUS_CACHES_TIME)
        return menu_all
